package com.jastar.android.game.go;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.Stack;

public class GoBoardView extends View {
    private static final int BOARD_SIZE = 13;
    private static final int[] STAR_POINTS = {3, 6, 9}; // 星位坐标

    private static final int BLACK = 1;
    private static final int WHITE = 2;
    private static final int EMPTY = 0;

    private AIPlayer aiPlayer;
    private boolean gameOver = false;

    private Stack<int[]> moveHistory = new Stack<>(); // 用于悔棋
    private boolean gameEnded = false;

    private int cellSize;    // 格子大小
    private int[][] board;   // 棋盘状态
    private int currentPlayer = BLACK; // 当前玩家（1=黑棋，2=白棋）
    private Paint gridPaint, gridBgPaint, blackPaint, whitePaint, whiteBorderPaint, starPaint, cursorPaint;
    private EventListener touchListener;
    private EventListener gameEndListener;

    private int cursorX = BOARD_SIZE / 2;
    private int cursorY = BOARD_SIZE / 2;

    public void addAIPlayer() {
        this.aiPlayer = new AIPlayer();
    }

    public GoBoardView(Context context) {
        super(context);
        init();
    }

    public GoBoardView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        gridPaint = new Paint();
        gridPaint.setColor(Color.BLACK);
        gridPaint.setStrokeWidth(2);

        gridBgPaint = new Paint();
        gridBgPaint.setColor(0xFFDECFAD);
        gridBgPaint.setStyle(Paint.Style.FILL);

        blackPaint = new Paint();
        blackPaint.setColor(Color.BLACK);
        blackPaint.setStyle(Paint.Style.FILL);

        whitePaint = new Paint();
        whitePaint.setColor(Color.WHITE);
        whitePaint.setStyle(Paint.Style.FILL);

        whiteBorderPaint = new Paint();
        whiteBorderPaint.setColor(Color.BLACK);
        whiteBorderPaint.setStyle(Paint.Style.STROKE);
        whiteBorderPaint.setStrokeWidth(1);

        starPaint = new Paint();
        starPaint.setColor(Color.BLACK);
        starPaint.setStyle(Paint.Style.FILL);

        cursorPaint = new Paint();
        cursorPaint.setStyle(Paint.Style.STROKE);
        cursorPaint.setStrokeWidth(3);

        board = new int[BOARD_SIZE][BOARD_SIZE];
    }

    private final AIPlayer.BoardState boardState = new AIPlayer.BoardState() {
        @Override
        public int[][] getBoard() {
            return board;
        }

        @Override
        public boolean isValidMove(int row, int col) {
            return isValidMove(row, col);
        }
    };

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
        cellSize = size / BOARD_SIZE;
        setMeasuredDimension(size, size);
    }

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        drawGrid(canvas);
        drawStarPoints(canvas);
        drawPieces(canvas);
        drawCursor(canvas);
    }

    private void drawGrid(Canvas canvas) {
        //画背景矩形
        canvas.drawRect(0, 0, BOARD_SIZE * cellSize, BOARD_SIZE * cellSize, gridBgPaint);
        for (int i = 0; i < BOARD_SIZE; i++) {
            float offset = cellSize / 2f;
            float pos = i * cellSize;
            // 画横线
            canvas.drawLine(offset, pos + offset, BOARD_SIZE * cellSize - offset, pos + offset, gridPaint);
            // 画竖线
            canvas.drawLine(pos + offset, offset, pos + offset, BOARD_SIZE * cellSize - offset, gridPaint);
        }
    }

    private void drawStarPoints(Canvas canvas) {
        for (int x : STAR_POINTS) {
            for (int y : STAR_POINTS) {
                float cx = x * cellSize + cellSize / 2f;
                float cy = y * cellSize + cellSize / 2f;
                canvas.drawCircle(cx, cy, 5, starPaint);
            }
        }
    }

    private void drawPieces(Canvas canvas) {
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                if (board[i][j] != EMPTY) {
                    float cx = i * cellSize + cellSize / 2f;
                    float cy = j * cellSize + cellSize / 2f;
                    if (board[i][j] == BLACK) {
                        canvas.drawCircle(cx, cy, cellSize / 2f - 5, blackPaint);
                    } else if (board[i][j] == WHITE) {
                        canvas.drawCircle(cx, cy, cellSize / 2f - 5, whitePaint);
                        canvas.drawCircle(cx, cy, cellSize / 2f - 5, whiteBorderPaint);
                    }
                }
            }
        }
    }

    private void drawCursor(Canvas canvas) {
        float left = cursorX * cellSize;
        float top = cursorY * cellSize;
        float right = (cursorX + 1) * cellSize;
        float bottom = (cursorY + 1) * cellSize;

        cursorPaint.setColor(getCurrentPlayer() == BLACK ? Color.BLACK : Color.WHITE);
        canvas.drawRect(left, top, right, bottom, cursorPaint);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (isCurrentAI()) return super.onKeyDown(keyCode, event);
        int newX = cursorX;
        int newY = cursorY;

        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_LEFT:
                newX = Math.max(0, cursorX - 1);
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                newX = Math.min(12, cursorX + 1);
                break;
            case KeyEvent.KEYCODE_DPAD_UP:
                newY = Math.max(0, cursorY - 1);
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:
                newY = Math.min(12, cursorY + 1);
                break;
            case KeyEvent.KEYCODE_DPAD_CENTER:  //一般遥控的确认键
            case KeyEvent.KEYCODE_BUTTON_1:     //某些设备的确认键
            case KeyEvent.KEYCODE_ENTER:
                handDown(cursorX, cursorY);
                return true;
            default:
                return super.onKeyDown(keyCode, event);
        }

        if (newX != cursorX || newY != cursorY) {
            cursorX = newX;
            cursorY = newY;
            invalidate();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isCurrentAI()) return super.onTouchEvent(event);
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            int x = (int) (event.getX() / cellSize);
            int y = (int) (event.getY() / cellSize);
            if (handDown(x, y)) return true;
        }
        return super.onTouchEvent(event);
    }

    private boolean isCurrentAI() {
        return !gameOver && null != this.aiPlayer && currentPlayer == WHITE;
    }

    private boolean handDown(int x, int y) {
        if (gameOver || gameEnded) return false;
        if (isValidMove(x, y)) {
            board[x][y] = currentPlayer;

            // 记录落子历史
            moveHistory.push(new int[]{x, y, currentPlayer});

            // 应用围棋规则：提子
            GoRules.captureStones(board, x, y, currentPlayer);

            currentPlayer = currentPlayer == BLACK ? WHITE : BLACK;
            touchListener.onEvent(currentPlayer, null);
            if (isCurrentAI()) aiMove();
            invalidate();
            return true;
        }
        return false;
    }

    private boolean isValidMove(int row, int col) {
        return GoRules.isValidMove(board, row, col, currentPlayer);
    }

    public boolean undoMove() {
        if (moveHistory.isEmpty() || isCurrentAI()) {
            return false;
        }

        int[] lastMove = moveHistory.pop();
        int x = lastMove[0];
        int y = lastMove[1];
        int player = lastMove[2];

        board[x][y] = EMPTY;
        currentPlayer = player;
        invalidate();
        return true;
    }

    // 添加计算胜负方法
    public void calculateWinner() {
        int[] scores = GoRules.calculateScore(board);
        int winner = scores[0] > scores[1] ? BLACK : (scores[0] < scores[1] ? WHITE : EMPTY);
        gameEnded = true;
        if (gameEndListener != null) {
            gameEndListener.onEvent(winner, scores);
        }
    }

    private void aiMove() {
        int[] move = aiPlayer.makeMove(boardState);
        if (move[0] != -1) {
            postDelayed(() -> handDown(move[0], move[1]), 1000); //添加延时动画
        }
    }

    public interface EventListener {
        void onEvent(int player, Object extra);
    }

    public void setTouchListener(EventListener listener) {
        this.touchListener = listener;
    }

    public void setOnGameEndListener(EventListener listener) {
        this.gameEndListener = listener;
    }

    public int getCurrentPlayer() {
        return currentPlayer;
    }

    public void setCurrentPlayer(int currentPlayer) {
        this.currentPlayer = currentPlayer;
    }

}